/**
 * 模式匹配工具类型：
 * 这一部分的工具类型主要使用 条件类型 与 infer 关键字。
 * 在 15_类型里的逻辑运算_2、infer 关键字.ts 中介绍了 infer 关键字，
 * 更严格地说 infer 其实代表了一种 模式匹配（pattern matching） 的思路
*/
/**
 * 首先是对函数类型签名的模式匹配：
 * 根据 infer 的位置不同，就能够获取到 不同位置 的类型，在函数这里则是 参数类型 与 返回值类型。
*/
type FunctionType = (...args: any) => any;
type Parameters<T extends FunctionType> = T extends (...args: infer P) => any ? P : never;
type ReturnType<T extends FunctionType> = T extends (...args: any) => infer R ? R : any;

//比如只匹配第一个参数类型：
type FirstParameter<T extends FunctionType> = T extends (
    arg: infer P,
    ...args: any
) => any
    ? P
    : never;
type FuncFoo = (arg: number, arg1: string) => void;
type FooFirstParameter = FirstParameter<FuncFoo>; // number

type FuncBar = (...args: string[]) => void;
type BarFirstParameter = FirstParameter<FuncBar>; // string

/**
 * 内置工具类型 中还有对 Class 进行 模式匹配 的工具类型：
*/
type ClassType = abstract new (...args: any) => any;
type ConstructorParameters<T extends ClassType> = T extends abstract new (
    ...args: infer P
) => any
    ? P
    : never;
type InstanceType<T extends ClassType> = T extends abstract new (
    ...args: any
) => infer R
    ? R
    : any;

//export {}：解决“无法重新声明块范围变量”错误提示问题
export { }